#include "musicwidget.h"

MusicWidget::MusicWidget(QWidget *parent) : QWidget(parent)
{
    // 1.主布局
    QHBoxLayout *mlayout = new QHBoxLayout(this);

    // 2.左布局
    QVBoxLayout *second_layout = new QVBoxLayout;
    // 2.1 上部
    QHBoxLayout *third_layout = new QHBoxLayout;
    // 2.1.1 播放列表
    list_widget = new QListWidget;
    list_widget->setCurrentRow(0); // 设置初始行为第一行
    list_widget->setEnabled(false);
    // 2.1.2 歌词
    lyricLabel = new QLabel("歌  词");
    lyricLabel->setAlignment(Qt::AlignCenter);
    lyricLabel->setFont(QFont("宋体", 14));
    // 2.2 中部，进度条
    QHBoxLayout *duration_lagout = new QHBoxLayout;
    current_label = new QLabel("00:00");
    duration_slider = new QSlider(Qt::Horizontal);
    duration_slider->setEnabled(false);
    total_label = new QLabel("00:00");
    // 2.3 下部，按键
    QHBoxLayout *btn_layout = new QHBoxLayout;
    last_btn = new QPushButton("上一首");
    play_btn = new QPushButton("播  放");
    next_btn = new QPushButton("下一首");
    last_btn->setEnabled(false);
    play_btn->setEnabled(false);
    next_btn->setEnabled(false);
    // 2.4 添加到布局
    third_layout->addWidget(list_widget);
    third_layout->addWidget(lyricLabel, 1);
    duration_lagout->addWidget(current_label, 0);
    duration_lagout->addWidget(duration_slider, 1);
    duration_lagout->addWidget(total_label, 0);
    btn_layout->addWidget(last_btn);
    btn_layout->addWidget(play_btn);
    btn_layout->addWidget(next_btn);
    second_layout->addLayout(third_layout, 1);
    second_layout->addLayout(duration_lagout, 0);
    second_layout->addLayout(btn_layout, 0);
    mlayout->addLayout(second_layout, 1);

    // 3.右布局，音量
    // 3.1 显示容器
    QFrame *sunken_frame = new QFrame();
    sunken_frame->setFrameStyle(QFrame::Panel | QFrame::Sunken); // 凹陷边框效果
    sunken_frame->setLineWidth(3); // 粗细
    // 3.2 子布局
    QVBoxLayout *vol_layout = new QVBoxLayout(sunken_frame);
    // 3.3 音量图标
    QLabel *sound_slider = new QLabel;
    sound_slider->setPixmap(QPixmap("://image/sound.png"));
    // 3.4 音量条
    volume_slider = new QSlider(Qt::Vertical);
    volume_slider->setEnabled(false);
    volume_slider->setValue(50); // 设置初始值为50
    // 3.5 音量数值
    volume_label = new QLabel("50");
    volume_label->setAlignment(Qt::AlignCenter); // 居中
    // 3.6 添加到布局
    vol_layout->addWidget(sound_slider);
    vol_layout->addWidget(volume_slider, 1);
    vol_layout->addWidget(volume_label);
    mlayout->addWidget(sunken_frame);

    // 4.播放列表
    // 4.1 创建播放列表
    playlist = new QMediaPlaylist;
    playlist->setPlaybackMode(QMediaPlaylist::Loop); // 循环模式
    // 4.2 不用fileDialog，而是直接打开文件夹扫描
    QDir music_dir(QDir::currentPath() + "./music"); // 本程序运行目录下music目录
    if(!music_dir.exists())
    {
        QMessageBox::critical(this, "打开失败", "无法找到music文件夹");
        this->close();
        return;
    }
    // 4.3 获取本目录内的所有文件
    QStringList music_file_fileter = {"*.mp3", "*.wav"}; // 创建一个筛选条件
    QStringList music_file_names = music_dir.entryList(music_file_fileter); // 依据筛选条件列出所有文件名
    for(QString name : music_file_names)
    {
        // 利用文件名获取文件完整且绝对的路径
        QString full_path = music_dir.absoluteFilePath(name);
        // 用绝对路径生成url对象
        QUrl url(full_path);
        // 用url生成媒体内容类
        QMediaContent content(url);
        // 将媒体内容类插入列表类，并将文件名插入显示的列表
        if(playlist->addMedia(content))
            list_widget->addItem(name);
    }

    // 5.播放器
    player = new QMediaPlayer;
    player->setVolume(50); // 设置初始值为50，与滑动条相同
    player->setPlaylist(playlist); // 绑定播放列表

    QString musicPath = playlist->currentMedia().canonicalUrl().path();
    QString lyPath = musicPath.left(musicPath.lastIndexOf('.')) + ".lrc";
    loadLyrics(lyPath);

    // 6.创建服务器
    tcpServer = tcpServerSingleton::create_tcpServer();

    // 7.信号/槽函数
    // 7.1 接收服务端信号
    this->connect(tcpServer, &tcpServerSingleton::sig_recv, this, [this](const QString recv){
        if(recv == "400")
        {
            list_widget->setEnabled(false);
            last_btn->setEnabled(false);
            play_btn->setEnabled(false);
            next_btn->setEnabled(false);
        }
        else if(recv == "401")
        {
            list_widget->setEnabled(true);
            last_btn->setEnabled(true);
            play_btn->setEnabled(true);
            next_btn->setEnabled(true);
        }
    });

    // 7.2 上一首
    this->connect(last_btn, &QPushButton::clicked, this, &MusicWidget::slot_last_music);
    // 7.3 播放/暂停
    this->connect(play_btn, &QPushButton::clicked, this, &MusicWidget::slot_play_music);
    // 7.4 下一首
    this->connect(next_btn, &QPushButton::clicked, this, &MusicWidget::slot_next_music);

    // 7.5.播放清单
    // 6.5.1 双击播放列表会播放
    this->connect(list_widget, &QListWidget::doubleClicked, this, [this](const QModelIndex &mIndex){
        playlist->setCurrentIndex(mIndex.row());
        player->play();
        duration_slider->setEnabled(true);
        volume_slider->setEnabled(true);
        play_btn->setText("暂  停");
    });
    // 7.5.2 播放列表变化时，反应到界面的list
    this->connect(playlist, &QMediaPlaylist::currentIndexChanged, this, [this](int index){
        // 更新当前播放索引
        playlist->setCurrentIndex(index);

        // 加载对应歌词文件
        QMediaContent currentMedia = playlist->media(index);
        QString musicFilePath = currentMedia.canonicalUrl().path();
        QString lrcFilePath = musicFilePath.left(musicFilePath.lastIndexOf('.')) + ".lrc";

        // 加载新歌词
        loadLyrics(lrcFilePath);

        // 更新界面
        list_widget->setCurrentRow(index);
    });

    // 7.6 音量调节
    this->connect(volume_slider, &QSlider::sliderMoved, this, [this](int pos){
        player->setVolume(pos);
        volume_label->setText(QString::number(pos));
    });

    // 7.7 进度调节
    // 7.7.1 进度条的变化
    this->connect(duration_slider, &QSlider::sliderMoved, this, [this](int pos){
        player->setPosition(pos * 1000);
    });
    // 7.7.2 当前时间的变化
    this->connect(player, &QMediaPlayer::positionChanged, this, [this](quint64 pos){
        pos /= 1000;
        current_label->setText(QString::number(pos / 60) + ":" + QString::number(pos % 60));
    });
    // 7.7.3 总时长的变化
    this->connect(player, &QMediaPlayer::durationChanged, this, [this](quint64 dura){
        dura /= 1000;
        total_label->setText(QString::number(dura / 60) + ":" + QString::number(dura % 60));

        // 设置上下限，并初始化滑动条位置
        duration_slider->setMaximum(dura - 1);
        duration_slider->setValue(0);
    });

    // 连接播放位置变化信号
    connect(player, &QMediaPlayer::positionChanged, this, &MusicWidget::updateLyric);
}

void MusicWidget::loadLyrics(const QString &filePath)
{
    QFile file(filePath);
    if (!file.exists())
    {
        QMessageBox::warning(this, "错误", "未找到歌词文件：" + filePath);
        return;
    }

    // 清空旧歌词（避免重复）
    lyricMap.clear();
    currentLyric.clear();

    // 读取新歌词
    if (file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QTextStream in(&file);
        in.setCodec("UTF-8");
        while (!in.atEnd())
        {
            QString line = in.readLine();
            QRegExp rx("\\[(\\d{2}):(\\d{2}\\.\\d{2})\\](.*)");
            if (rx.indexIn(line) != -1)
            {
                int time = rx.cap(1).toInt() * 60000 + rx.cap(2).toFloat() * 1000;
                QString lyric = rx.cap(3).trimmed();
                lyricMap.insert(time, lyric);
            }
        }
        file.close();
    }
}

void MusicWidget::updateLyric(qint64 position)
{
    int currentTime = position;
    QMap<int, QString>::const_iterator i = lyricMap.upperBound(currentTime);

    if (i != lyricMap.constBegin())
    {
        --i;
        if (i.key() <= currentTime)
        {
            currentLyric = i.value();
        }
        else
        {
            currentLyric = "";
        }
    }
    else
    {
        currentLyric = "";
    }

    // 动态滚动效果
    static int lastPos = 0;
    if (lyricLabel->pos().y() != lastPos)
    {
        QPropertyAnimation *animation = new QPropertyAnimation(lyricLabel, "pos");
        animation->setDuration(500);
        animation->setStartValue(lyricLabel->pos());
        animation->setEndValue(QPoint(lyricLabel->x(), lastPos + 20));
        animation->start();
    }
    lastPos = lyricLabel->pos().y();

    lyricLabel->setText(currentLyric);
}

void MusicWidget::slot_last_music()
{
    // 1.播放列表选中上一曲，并将上一曲内容推送到player内开始播放
    playlist->previous();
    player->play();

    // 2.更新设置和标签
    // 2.1 启用并更新进度条
    duration_slider->setEnabled(true);
    // 2.2 启用并更新音量
    volume_slider->setEnabled(true);
    // 2.3 将“播放”修改为“暂停”
    play_btn->setText("暂  停");
}
void MusicWidget::slot_play_music()
{
    // 判断当前是否正在播放
    if(player->state() == QMediaPlayer::PlayingState)
    {
        // 如果正在播放则暂停，并更新设置和标签
        player->pause();
        play_btn->setText("播  放");
        duration_slider->setEnabled(false);
        volume_slider->setEnabled(false);
    }
    else
    {
        // 如果没有播放则播放，并更新设置和标签
        player->play();
        play_btn->setText("暂  停");
        duration_slider->setEnabled(true);
        volume_slider->setEnabled(true);
    }
}
void MusicWidget::slot_next_music()
{
    // 1.播放列表选中下一曲，并下一曲内容推送到player内开始播放
    playlist->next();
    player->play();

    // 2.更新设置和标签
    // 2.1 启用并更新进度条
    duration_slider->setEnabled(true);
    // 2.2 启用并更新音量
    volume_slider->setEnabled(true);
    // 2.3 将“播放”修改为“暂停”
    play_btn->setText("暂  停");
}

void MusicWidget::paintEvent(QPaintEvent *e)
{
    // 1.创建画家，并绑定窗口
    QPainter painter(this);

    // 2.添加图片背景
    QPixmap pixmap("://image/yasna.jpg");
    painter.drawPixmap(0, 0, this->width(), this->height(), pixmap); // 绘制图片背景
}
